import dayjs from "dayjs";

//身份证号码前17位数分别乘以不同的系数
const ratio = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
//将这17位数字和系数相乘的结果相加,对11进行求余，得出身份证最后一个字符
const matchMap = {
  0: "1",
  1: "0",
  2: "X",
  3: "9",
  4: "8",
  5: "7",
  6: "6",
  7: "5",
  8: "4",
  9: "3",
  10: "2",
};

/**
 * 验证身份证是否正确
 * @param IDNum
 * @returns {boolean}
 */
export function verifyIDNum(IDNum) {
  const IDNUM_LENGTH = 18;
  const RATIO_VALUE = 11;
  if (!IDNum) return false;
  if (IDNum.length !== IDNUM_LENGTH) {
    return false;
  }
  //验证生日合法性
  if (!verifyBirthday(IDNum.slice(6, 14))) {
    return false;
  }
  const lastChar = IDNum.slice(IDNUM_LENGTH - 1);
  const pre17Char = IDNum.slice(0, IDNUM_LENGTH - 1);
  const charList = pre17Char.split("");
  let totalCount = 0;
  if (!/^(\d|X)$/.test(lastChar)) {
    return false;
  }
  for (let i = 0, len = charList.length; i < len; i++) {
    if (isNaN(Number(charList[i]))) {
      return false;
    }
    totalCount += Number(charList[i]) * ratio[i];
  }
  return matchMap[totalCount % RATIO_VALUE] === lastChar;
}

export function getBirthday(IDNum) {
  if (!IDNum) {
    return null;
  }
  return dayjs(IDNum.slice(6, 15), "YYYYMMDD").format("YYYY-MM-DD");
}
/**
 * @param IDNum
 * @returns {string} 男：'1'，女：'2'
 */
export function getSex(IDNum) {
  return IDNum.slice(-2, -1) % 2 === 0 ? "2" : "1";
}
export function getAge(IDNum) {
  return dayjs().diff(dayjs(IDNum.substr(6, 8), "YYYYMMDD"), "year");
}

export function formatIDNum(IDNum) {
  if (IDNum?.startsWith("'")) IDNum = IDNum.substr(1);
  return IDNum;
}

function verifyBirthday(birthday) {
  // 验证生日合法性
  let year = birthday.slice(0, 4),
    month = birthday.slice(4, 6),
    date = birthday.slice(6, 8);
  let flag = false;
  if (isNaN(Number(year)) || isNaN(Number(month)) || isNaN(Number(date))) {
    return false;
  }
  (year = Number(year)), (month = Number(month)), (date = Number(date));
  if (year > new Date().getFullYear()) {
    return false;
  }
  let FebDay = 28;
  if (leapYear(year)) {
    FebDay = 29;
  }
  switch (month) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
      flag = inRange(date, 1, 31);
      break;
    case 2:
      flag = inRange(date, 1, FebDay);
      break;
    case 4:
    case 6:
    case 9:
    case 11:
      flag = inRange(date, 1, 30);
      break;
  }
  return flag;
}

function leapYear(year) {
  return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
}

function inRange(val, min, max) {
  return val >= min && val <= max;
}
